<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>2048游戏</title>
    <style>
            * {
                margin: 0;
                padding: 0;
                box-sizing: border-box;
                font-family: Arial, sans-serif;
            }
            
            body {
                display: flex;
                flex-direction: column;
                align-items: center;
                background-color: #faf8ef;
                padding: 20px;
            }
            
            .game-container {
                text-align: center;
            }
            
            h1 {
                font-size: 80px;
                color: #776e65;
                margin-bottom: 20px;
            }
            
            .game-info {
                display: flex;
                justify-content: space-between;
                margin-bottom: 20px;
                width: 500px;
            }
            
            .score-container {
                background-color: #bbada0;
                padding: 10px 20px;
                border-radius: 5px;
                color: #eee4da;
                font-weight: bold;
                display: flex;
                flex-direction: column;
                align-items: center;
            }
            
            .difficulty-container {
                background-color: #bbada0;
                padding: 10px 20px;
                border-radius: 5px;
                color: white;
                font-weight: bold;
            }
            
            .difficulty-container select {
                background-color: white;
                border: none;
                padding: 5px 10px;
                border-radius: 3px;
                font-weight: bold;
                color: #776e65;
                margin-top: 5px;
            }
        
        .score-container .score {
            color: white;
            font-size: 25px;
        }
        
        .game-board {
            width: 500px;
            height: 500px;
            background-color: #bbada0;
            border-radius: 10px;
            padding: 15px;
            position: relative;
        }
        
        .grid-container {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            grid-template-rows: repeat(4, 1fr);
            gap: 15px;
            width: 100%;
            height: 100%;
        }
        
        .grid-cell {
            background-color: rgba(238, 228, 218, 0.35);
            border-radius: 5px;
        }
        
        .tile {
            width: 100%;
            height: 100%;
            border-radius: 5px;
            display: flex;
            justify-content: center;
            align-items: center;
            font-weight: bold;
            font-size: 55px;
            transition: all 0.15s ease-out;
            will-change: transform, opacity;
            z-index: 10;
        }
        
        /* 移动动画类 */
        .tile-move-up {
            transform: translateY(-100%);
        }
        
        .tile-move-down {
            transform: translateY(100%);
        }
        
        .tile-move-left {
            transform: translateX(-100%);
        }
        
        .tile-move-right {
            transform: translateX(100%);
        }
        
        /* 合并动画类 */
        .tile-merged {
            animation: mergeAnimation 0.2s ease-in-out;
            z-index: 20;
        }
        
        /* 新方块出现动画 */
        .tile-new {
            animation: appearAnimation 0.3s ease-out;
        }
        
        @keyframes mergeAnimation {
            0% {
                transform: scale(1);
            }
            50% {
                transform: scale(1.2);
            }
            100% {
                transform: scale(1);
            }
        }
        
        @keyframes appearAnimation {
            0% {
                opacity: 0;
                transform: scale(0.5);
            }
            100% {
                opacity: 1;
                transform: scale(1);
            }
        }
        
        .tile-2 {
            background-color: #eee4da;
            color: #776e65;
        }
        
        .tile-4 {
            background-color: #ede0c8;
            color: #776e65;
        }
        
        .tile-8 {
            background-color: #f2b179;
            color: white;
        }
        
        .tile-16 {
            background-color: #f59563;
            color: white;
        }
        
        .tile-32 {
            background-color: #f67c5f;
            color: white;
        }
        
        .tile-64 {
            background-color: #f65e3b;
            color: white;
        }
        
        .tile-128 {
            background-color: #edcf72;
            color: white;
        }
        
        .tile-256 {
            background-color: #edcc61;
            color: white;
        }
        
        .tile-512 {
            background-color: #edc850;
            color: white;
        }
        
        .tile-1024 {
            background-color: #edc53f;
            color: white;
            font-size: 45px;
        }
        
        .tile-2048 {
            background-color: #edc22e;
            color: white;
            font-size: 45px;
        }
        
        .game-over {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: rgba(238, 228, 218, 0.73);
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            border-radius: 10px;
            display: none;
            z-index: 100;
        }
        
        .game-over h2 {
            font-size: 60px;
            color: #776e65;
            margin-bottom: 20px;
        }
        
        button {
            background-color: #8f7a66;
            color: white;
            border: none;
            padding: 15px 30px;
            font-size: 18px;
            border-radius: 5px;
            cursor: pointer;
            font-weight: bold;
        }
        
        button:hover {
            background-color: #9f8a76;
        }
        
        .instructions {
            margin-top: 30px;
            color: #776e65;
            font-size: 16px;
        }
    </style>
</head>
<body>
    <div class="game-container">
        <h1>2048</h1>
        <div class="game-info">
            <div class="score-container">
                分数
                <div class="score" id="score">0</div>
            </div>
            <div class="score-container">
                最高分
                <div class="score" id="highScore">0</div>
            </div>
            <div class="difficulty-container">
                <select id="difficultySelect">
                    <option value="easy">极简难度</option>
                    <option value="normal" selected>普通难度</option>
                </select>
            </div>
            <button id="restartButton">重新开始</button>
        </div>
        <div class="game-board">
            <div class="grid-container">
                <!-- 网格背景将在JavaScript中动态生成 -->
            </div>
            <!-- 游戏结束遮罩 -->
            <div class="game-over" id="gameOver">
                <h2>游戏结束!</h2>
                <button id="tryAgainButton">再试一次</button>
            </div>
        </div>
        <div class="instructions">
            <p>使用键盘方向键或WASD键移动方块。相同数字的方块碰撞时会合并成它们的和。尝试合成2048！</p>
            <p><strong>极简难度特点：</strong>3x3小网格，更容易合并，更不容易结束游戏，适合新手！</p>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            // 游戏变量
            let grid = [];
            let score = 0;
            let highScore = localStorage.getItem('2048-high-score') || 0;
            let isGameOver = false;
            let gridSize = 4; // 默认4x4网格
            let difficulty = 'normal'; // 默认普通难度
            

            const difficultySelect = document.getElementById('difficultySelect');
            const gridContainer = document.querySelector('.grid-container');
            
            // 难度选择事件监听
            difficultySelect.addEventListener('change', () => {
                difficulty = difficultySelect.value;
                gridSize = difficulty === 'easy' ? 3 : 4;
                
                // 根据难度调整游戏板和网格大小
                if (difficulty === 'easy') {
                    gameBoard.style.width = '380px';
                    gameBoard.style.height = '380px';
                    gridContainer.style.gridTemplateColumns = 'repeat(3, 1fr)';
                    gridContainer.style.gridTemplateRows = 'repeat(3, 1fr)';
                } else {
                    gameBoard.style.width = '500px';
                    gameBoard.style.height = '500px';
                    gridContainer.style.gridTemplateColumns = 'repeat(4, 1fr)';
                    gridContainer.style.gridTemplateRows = 'repeat(4, 1fr)';
                }
                
                // 重新生成网格背景
                generateGridBackground();
                
                // 初始化游戏
                init();
            });
            
            // DOM 元素
            const scoreElement = document.getElementById('score');
            const highScoreElement = document.getElementById('highScore');
            const restartButton = document.getElementById('restartButton');
            const tryAgainButton = document.getElementById('tryAgainButton');
            const gameOverElement = document.getElementById('gameOver');
            const gameBoard = document.querySelector('.game-board');
            
            // 生成网格背景
            function generateGridBackground() {
                // 清空现有网格背景
                gridContainer.innerHTML = '';
                
                // 根据当前网格大小生成新的背景格子
                for (let i = 0; i < gridSize * gridSize; i++) {
                    const cell = document.createElement('div');
                    cell.classList.add('grid-cell');
                    gridContainer.appendChild(cell);
                }
            }
            
            // 初始化游戏
            function init() {
                // 重置网格
                grid = Array(gridSize).fill().map(() => Array(gridSize).fill(0));
                score = 0;
                isGameOver = false;
                gameOverElement.style.display = 'none';
                
                // 根据难度设置初始方块数量
                const initialTiles = difficulty === 'easy' ? 1 : 2;
                for (let i = 0; i < initialTiles; i++) {
                    addNewTile();
                }
                
                // 更新UI
                updateScore();
                updateHighScore();
                updateGrid();
            }
            
            // 添加新方块
            function addNewTile() {
                const emptyCells = [];
                
                // 找出所有空单元格
                for (let i = 0; i < gridSize; i++) {
                    for (let j = 0; j < gridSize; j++) {
                        if (grid[i][j] === 0) {
                            emptyCells.push({row: i, col: j});
                        }
                    }
                }
                
                // 如果有空单元格，随机选择一个添加新方块
                if (emptyCells.length > 0) {
                    const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)];
                    // 极简难度下更容易出现2，几乎不会出现4
                    const twoProbability = difficulty === 'easy' ? 0.98 : 0.9;
                    grid[randomCell.row][randomCell.col] = Math.random() < twoProbability ? 2 : 4;
                }
            }
            
            // 记录移动前的网格状态
        let previousGrid = null;
        
        function updateGrid() {
            // 记录当前网格状态，用于下次移动时计算方向
            const currentGrid = grid.map(row => [...row]);
            
            // 获取所有现有方块的位置信息
            const existingTiles = document.querySelectorAll('.tile');
            const tilePositions = {};
            
            existingTiles.forEach(tile => {
                const row = parseInt(tile.style.gridRow) - 1;
                const col = parseInt(tile.style.gridColumn) - 1;
                if (previousGrid && previousGrid[row][col] !== 0) {
                    tilePositions[previousGrid[row][col]] = { row, col, element: tile };
                }
            });
            
            // 移除所有现有方块
            existingTiles.forEach(tile => tile.remove());
            
            // 添加当前方块，并应用动画
            for (let i = 0; i < gridSize; i++) {
                for (let j = 0; j < gridSize; j++) {
                    if (grid[i][j] !== 0) {
                        const tile = document.createElement('div');
                        tile.classList.add('tile', `tile-${grid[i][j]}`);
                        
                        // 使用CSS Grid布局定位方块，确保与背景格子对齐
                        tile.style.gridColumn = j + 1;
                        tile.style.gridRow = i + 1;
                        tile.textContent = grid[i][j];
                        
                        // 检查是否为新方块
                        const isNew = !previousGrid || previousGrid[i][j] !== grid[i][j];
                        
                        // 检查是否有移动轨迹
                        let hasMovement = false;
                        
                        // 如果是合成结果（数值翻倍）
                        if (previousGrid) {
                            let merged = false;
                            for (let x = 0; x < gridSize && !merged; x++) {
                                for (let y = 0; y < gridSize && !merged; y++) {
                                    if (previousGrid[x][y] !== 0 && previousGrid[x][y] * 2 === grid[i][j]) {
                                        // 检查是否是从该位置合并而来
                                        const adjacent = (
                                            (x === i && Math.abs(y - j) === 1) || 
                                            (y === j && Math.abs(x - i) === 1)
                                        );
                                        
                                        if (adjacent) {
                                            tile.classList.add('tile-merged');
                                            merged = true;
                                        }
                                    }
                                }
                            }
                        }
                        
                        // 如果是新方块，添加出现动画
                        if (isNew && !tile.classList.contains('tile-merged')) {
                            tile.classList.add('tile-new');
                        }
                        
                        gridContainer.appendChild(tile);
                    }
                }
            }
            
            // 更新previousGrid为当前状态
            previousGrid = currentGrid;
        }
            
            // 更新分数
            function updateScore() {
                scoreElement.textContent = score;
            }
            
            // 更新最高分
            function updateHighScore() {
                if (score > highScore) {
                    highScore = score;
                    localStorage.setItem('2048-high-score', highScore);
                }
                highScoreElement.textContent = highScore;
            }
            
            // 检查游戏是否结束
            function checkGameOver() {
                // 先检查是否真的无法移动（复制当前网格进行测试）
                const testGrid = grid.map(row => [...row]);
                
                // 测试所有四个方向的移动
                let canMove = false;
                canMove = canMove || testMove('up', testGrid);
                canMove = canMove || testMove('down', testGrid);
                canMove = canMove || testMove('left', testGrid);
                canMove = canMove || testMove('right', testGrid);
                
                // 如果还能移动，肯定不结束游戏
                if (canMove) return false;
                
                // 极简难度下，游戏极难结束
                if (difficulty === 'easy') {
                    // 98%的概率不结束游戏
                    if (Math.random() < 0.98) {
                        // 确保找到一个非空格子来清空
                        const nonEmptyPositions = [];
                        for (let i = 0; i < gridSize; i++) {
                            for (let j = 0; j < gridSize; j++) {
                                if (grid[i][j] !== 0) {
                                    nonEmptyPositions.push({i, j});
                                }
                            }
                        }
                        
                        // 如果有非空格子，清空其中一个
                        if (nonEmptyPositions.length > 0) {
                            const randomIndex = Math.floor(Math.random() * nonEmptyPositions.length);
                            const {i, j} = nonEmptyPositions[randomIndex];
                            grid[i][j] = 0;
                            updateGrid();
                        }
                        
                        return false;
                    }
                }
                
                // 游戏结束
                isGameOver = true;
                gameOverElement.style.display = 'flex';
                return true;
            }
            
            // 测试移动函数（用于游戏结束检测）
            function testMove(direction, testGrid) {
                let hasChanged = false;
                const testGridCopy = testGrid.map(row => [...row]);
                
                switch (direction) {
                    case 'up':
                        for (let j = 0; j < gridSize; j++) {
                            for (let i = 1; i < gridSize; i++) {
                                if (testGridCopy[i][j] !== 0) {
                                    let row = i;
                                    while (row > 0 && testGridCopy[row - 1][j] === 0) {
                                        testGridCopy[row - 1][j] = testGridCopy[row][j];
                                        testGridCopy[row][j] = 0;
                                        row--;
                                        hasChanged = true;
                                    }
                                    if (row > 0 && testGridCopy[row - 1][j] === testGridCopy[row][j]) {
                                        hasChanged = true;
                                    }
                                }
                            }
                        }
                        break;
                    case 'down':
                        for (let j = 0; j < gridSize; j++) {
                            for (let i = gridSize - 2; i >= 0; i--) {
                                if (testGridCopy[i][j] !== 0) {
                                    let row = i;
                                    while (row < gridSize - 1 && testGridCopy[row + 1][j] === 0) {
                                        testGridCopy[row + 1][j] = testGridCopy[row][j];
                                        testGridCopy[row][j] = 0;
                                        row++;
                                        hasChanged = true;
                                    }
                                    if (row < gridSize - 1 && testGridCopy[row + 1][j] === testGridCopy[row][j]) {
                                        hasChanged = true;
                                    }
                                }
                            }
                        }
                        break;
                    case 'left':
                        for (let i = 0; i < gridSize; i++) {
                            for (let j = 1; j < gridSize; j++) {
                                if (testGridCopy[i][j] !== 0) {
                                    let col = j;
                                    while (col > 0 && testGridCopy[i][col - 1] === 0) {
                                        testGridCopy[i][col - 1] = testGridCopy[i][col];
                                        testGridCopy[i][col] = 0;
                                        col--;
                                        hasChanged = true;
                                    }
                                    if (col > 0 && testGridCopy[i][col - 1] === testGridCopy[i][col]) {
                                        hasChanged = true;
                                    }
                                }
                            }
                        }
                        break;
                    case 'right':
                        for (let i = 0; i < gridSize; i++) {
                            for (let j = gridSize - 2; j >= 0; j--) {
                                if (testGridCopy[i][j] !== 0) {
                                    let col = j;
                                    while (col < gridSize - 1 && testGridCopy[i][col + 1] === 0) {
                                        testGridCopy[i][col + 1] = testGridCopy[i][col];
                                        testGridCopy[i][col] = 0;
                                        col++;
                                        hasChanged = true;
                                    }
                                    if (col < gridSize - 1 && testGridCopy[i][col + 1] === testGridCopy[i][col]) {
                                        hasChanged = true;
                                    }
                                }
                            }
                        }
                        break;
                }
                
                return hasChanged;
            }
            
            // 移动方块 - 上
            function moveUp() {
                let hasChanged = false;
                
                for (let j = 0; j < gridSize; j++) {
                    // 合并相同数字的方块
                    for (let i = 1; i < gridSize; i++) {
                        if (grid[i][j] !== 0) {
                            let row = i;
                            // 移动到最上方可能的位置
                            while (row > 0 && grid[row - 1][j] === 0) {
                                grid[row - 1][j] = grid[row][j];
                                grid[row][j] = 0;
                                row--;
                                hasChanged = true;
                            }
                            // 尝试合并
                            if (row > 0 && grid[row - 1][j] === grid[row][j]) {
                                grid[row - 1][j] *= 2;
                                score += grid[row - 1][j];
                                grid[row][j] = 0;
                                hasChanged = true;
                            }
                        }
                    }
                }
                
                return hasChanged;
            }
            
            // 移动方块 - 下
            function moveDown() {
                let hasChanged = false;
                
                for (let j = 0; j < gridSize; j++) {
                    // 合并相同数字的方块
                    for (let i = gridSize - 2; i >= 0; i--) {
                        if (grid[i][j] !== 0) {
                            let row = i;
                            // 移动到最下方可能的位置
                            while (row < gridSize - 1 && grid[row + 1][j] === 0) {
                                grid[row + 1][j] = grid[row][j];
                                grid[row][j] = 0;
                                row++;
                                hasChanged = true;
                            }
                            // 尝试合并
                            if (row < gridSize - 1 && grid[row + 1][j] === grid[row][j]) {
                                grid[row + 1][j] *= 2;
                                score += grid[row + 1][j];
                                grid[row][j] = 0;
                                hasChanged = true;
                            }
                        }
                    }
                }
                
                return hasChanged;
            }
            
            // 移动方块 - 左
            function moveLeft() {
                let hasChanged = false;
                
                for (let i = 0; i < gridSize; i++) {
                    // 合并相同数字的方块
                    for (let j = 1; j < gridSize; j++) {
                        if (grid[i][j] !== 0) {
                            let col = j;
                            // 移动到最左侧可能的位置
                            while (col > 0 && grid[i][col - 1] === 0) {
                                grid[i][col - 1] = grid[i][col];
                                grid[i][col] = 0;
                                col--;
                                hasChanged = true;
                            }
                            // 尝试合并
                            if (col > 0 && grid[i][col - 1] === grid[i][col]) {
                                grid[i][col - 1] *= 2;
                                score += grid[i][col - 1];
                                grid[i][col] = 0;
                                hasChanged = true;
                            }
                        }
                    }
                }
                
                return hasChanged;
            }
            
            // 移动方块 - 右
            function moveRight() {
                let hasChanged = false;
                
                for (let i = 0; i < gridSize; i++) {
                    // 合并相同数字的方块
                    for (let j = gridSize - 2; j >= 0; j--) {
                        if (grid[i][j] !== 0) {
                            let col = j;
                            // 移动到最右侧可能的位置
                            while (col < gridSize - 1 && grid[i][col + 1] === 0) {
                                grid[i][col + 1] = grid[i][col];
                                grid[i][col] = 0;
                                col++;
                                hasChanged = true;
                            }
                            // 尝试合并
                            if (col < gridSize - 1 && grid[i][col + 1] === grid[i][col]) {
                                grid[i][col + 1] *= 2;
                                score += grid[i][col + 1];
                                grid[i][col] = 0;
                                hasChanged = true;
                            }
                        }
                    }
                }
                
                return hasChanged;
            }
            
            // 处理移动
            function handleMove(direction) {
                if (isGameOver) return;
                
                let hasChanged = false;
                
                switch (direction) {
                    case 'up':
                        hasChanged = moveUp();
                        break;
                    case 'down':
                        hasChanged = moveDown();
                        break;
                    case 'left':
                        hasChanged = moveLeft();
                        break;
                    case 'right':
                        hasChanged = moveRight();
                        break;
                }
                
                // 如果有变化，添加新方块并更新UI
                if (hasChanged) {
                    addNewTile();
                    updateGrid();
                    updateScore();
                    updateHighScore();
                    checkGameOver();
                }
            }
            
            // 事件监听
            document.addEventListener('keydown', (event) => {
                switch (event.key) {
                    case 'ArrowUp':
                    case 'w':
                    case 'W':
                        event.preventDefault();
                        handleMove('up');
                        break;
                    case 'ArrowDown':
                    case 's':
                    case 'S':
                        event.preventDefault();
                        handleMove('down');
                        break;
                    case 'ArrowLeft':
                    case 'a':
                    case 'A':
                        event.preventDefault();
                        handleMove('left');
                        break;
                    case 'ArrowRight':
                    case 'd':
                    case 'D':
                        event.preventDefault();
                        handleMove('right');
                        break;
                }
            });
            
            // 按钮事件
            restartButton.addEventListener('click', init);
            tryAgainButton.addEventListener('click', init);
            
            // 生成初始网格背景
            generateGridBackground();
            
            // 初始化游戏
            init();
        });
    </script>
</body>
</html>